//
//  ChatView.m
//  ENTBoostChat
//
//  Created by zhong zf on 14-8-15.
//  Copyright (c) 2014年 EB. All rights reserved.
//

#import "ChatView.h"
#import "RunningCache.h"
#import "ChatImage.h"
#import "ImageViewController.h"

@interface ChatView ()
{
    CTFrameRef _ctFrame;
    CTFramesetterRef _ctFramesetter;
}

@property(nonatomic) CTFrameRef ctFrame;

@end

@implementation ChatView

- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        // Initialization code
    }
    return self;
}

- (id)initWithCTFramesetterRef:(CTFramesetterRef)ctFramesetter andFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        self.ctFramesetter = ctFramesetter;
        self.ctFrame = NULL;
    }
    return self;
}

- (CTFramesetterRef)ctFramesetter
{
    return _ctFramesetter;
}

- (void)setCtFramesetter:(CTFramesetterRef)ctFramesetter
{
    //ctFramesetter非NSObject对象，需要手工进行release
    if (_ctFramesetter != NULL) {
        CFRelease(_ctFramesetter);
    }
    _ctFramesetter = ctFramesetter;
}

- (CTFrameRef)ctFrame
{
    return _ctFrame;
}

- (void)setCtFrame:(CTFrameRef)ctFrame
{
    //ctFrame非NSObject对象，需要手工进行release
    if (_ctFrame != NULL) {
        CFRelease(_ctFrame);
    }
    _ctFrame = ctFrame;
}

- (void)dealloc
{
    self.ctFramesetter = NULL;
    self.ctFrame = NULL;
}

- (void)drawRect:(CGRect)rect
{
//    NSLog(@"drawRect %@", NSStringFromCGRect(rect));
//    if(!self.attributedString) {
//        NSLog(@"no attributedString");
//        return;
//    }

    if(!self.ctFramesetter) {
        NSLog(@"no ctFramesetter");
        return;
    }
    
    //保存上下文
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextSaveGState(context);
    
    //转换被反转的坐标系
    CGContextSetTextMatrix(context, CGAffineTransformIdentity);//设置字形变换矩阵为CGAffineTransformIdentity，也就是说每一个字形都不做图形变换
    CGAffineTransform flipVertical = CGAffineTransformMake(1, 0, 0, -1, 0, rect.size.height);
    CGContextConcatCTM(context, flipVertical);//将当前context的坐标系进行flip

    //创建帧管理器
    //CTFramesetterRef ctFramesetter = CTFramesetterCreateWithAttributedString((__bridge CFMutableAttributedStringRef)self.attributedString);
    
    //CGSize suggestedSize =CTFramesetterSuggestFrameSizeWithConstraints(ctFramesetter,CFRangeMake(0, 0), NULL,CGSizeMake(CONTENT_MAX_HEIGHT, 100), NULL);
    
    //创建绘图路径并把设置矩形参数
    CGMutablePathRef path = CGPathCreateMutable();
    CGRect bounds = CGRectMake(0.0, 0.0, rect.size.width, rect.size.height);
    CGPathAddRect(path, NULL, bounds);
    
    //创建一个帧并在上下文执行绘制文本
    self.ctFrame = CTFramesetterCreateFrame(self.ctFramesetter, CFRangeMake(0, 0), path, NULL);
//    CFRange frameRange = CTFrameGetVisibleStringRange(self.ctFrame);
//    NSLog(@"frame location:%li, length:%li", frameRange.location, frameRange.length);
    CTFrameDraw(self.ctFrame, context);
    
    //获取帧中所有行
    CFArrayRef lines = CTFrameGetLines(self.ctFrame);
    
    //获取行数
    CFIndex lineCount = CFArrayGetCount(lines);
    
    //获取各行的起始坐标
    CGPoint lineOrigins[lineCount];
    CTFrameGetLineOrigins(self.ctFrame, CFRangeMake(0, 0), lineOrigins);
//    NSLog(@"line count = %ld", lineCount);
    
    //循环处理每行数据，检查是否需要绘制图片
    for (int i = 0; i < lineCount; i++) {
        //获取单行
        CTLineRef line = CFArrayGetValueAtIndex(lines, i);
        
        //当前行起点坐标
        CGPoint lineOrigin = lineOrigins[i];
        
        //获取单行的印刷(真实绘制)大小信息(宽度、高度、左间距等)
//        CGFloat lineAscent;
//        CGFloat lineDescent;
//        CGFloat lineLeading;
//        double lineWidth = CTLineGetTypographicBounds(line, &lineAscent, &lineDescent, &lineLeading);
//        NSLog(@"line width = %f, ascent = %f, descent = %f, leading = %f", lineWidth, lineAscent, lineDescent, lineLeading);
        
        //获取单行中的CTRun实例列表
        CFArrayRef runs = CTLineGetGlyphRuns(line);
        CFIndex runCount = CFArrayGetCount(runs);
        //NSLog(@"ctRun count = %ld", runCount);
        
        //循环检查每一个CTRun实例
        for (int j = 0; j < runCount; j++) {
            //获取一个CTRun实例
            CTRunRef run = CFArrayGetValueAtIndex(runs, j);
            
            //获取一个CTRun的印刷(真实绘制)大小信息(宽度、高度、左间距等)
            CGFloat runAscent;
            CGFloat runDescent;
            CGFloat runLeading;
            double runWidth = CTRunGetTypographicBounds(run, CFRangeMake(0,0), &runAscent, &runDescent, &runLeading);
            //NSLog(@"ctRun width = %f ascent = %f, descent = %f, leading = %f", runWidth, runAscent, runDescent, runLeading);
            
            //计算当前CTRun的维度信息(起点、宽度、高度等)
            CGRect runRect = CGRectMake(lineOrigin.x + CTLineGetOffsetForStringIndex(line, CTRunGetStringRange(run).location, NULL), lineOrigin.y - runDescent, runWidth, runAscent + runDescent);
            
            //NSLog(@"runRect %@", NSStringFromCGRect(runRect));
            
            //获取属性字典
            NSDictionary* attributes = (__bridge NSDictionary*)CTRunGetAttributes(run);
            NSString *imageTag = [attributes objectForKey:CHAT_IMAGE_TAG_NAME];
            
            //判断是否图片并执行渲染
            if (imageTag) {
                ChatImage* chatImage = [[RunningCache sharedCache] chatImageForTag:imageTag];
                if (chatImage) {
//                    UIImage *image = chatImage.scaleImage;
                    CGRect imageDrawRect = CGRectMake(runRect.origin.x, runRect.origin.y, runRect.size.width, runRect.size.height);
                    //NSLog(@"imageDrawRect %@", NSStringFromCGRect(imageDrawRect));
//                    imageDrawRect.size = runRect.size;
//                    imageDrawRect.origin.x = runRect.origin.x;
//                    imageDrawRect.origin.y = runRect.origin.y;
                    CGContextDrawImage(context, imageDrawRect, chatImage.scaleImage.CGImage);
                }
            }
        }
    }
    
//    CFRelease(ctFrame);
    CFRelease(path);
    //CFRelease(ctFramesetter);
    
    CGContextRestoreGState(context);
}

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    if(!self.ctFrame)
        return;
    
    //获取UITouch对象
    UITouch *touch = [touches anyObject];
    //获取触摸点击当前view的坐标位置
    CGPoint location = [touch locationInView:self];
    //获取每一行
    CFArrayRef lines = CTFrameGetLines(self.ctFrame);
    CGPoint origins[CFArrayGetCount(lines)];
    //获取每行的原点坐标
    CTFrameGetLineOrigins(self.ctFrame, CFRangeMake(0, 0), origins);
    CTLineRef line = NULL;
    CGPoint lineOrigin = CGPointZero;
    for (int i= 0; i < CFArrayGetCount(lines); i++)
    {
        CGPoint origin = origins[i];
        CGPathRef path = CTFrameGetPath(self.ctFrame);
        //获取整个CTFrame的大小
        CGRect rect = CGPathGetBoundingBox(path);
        //坐标转换，把每行的原点坐标转换为uiview的坐标体系
        CGFloat y = rect.origin.y + rect.size.height - origin.y;
        //判断点击的位置处于那一行范围内
        if ((location.y <= y) && (location.x >= origin.x))
        {
            line = CFArrayGetValueAtIndex(lines, i);
            lineOrigin = origin;
            break;
        }
    }
    
    if(!line)
        return;
    
    location.x -= lineOrigin.x;
    //获取点击位置所处的字符位置，就是相当于点击了第几个字符
    CFIndex index = CTLineGetStringIndexForPosition(line, location);
    
    //遍历所点击行中的所有CTRun，匹配被点击的图片
    CFArrayRef runs = CTLineGetGlyphRuns(line);
    CFIndex runCount = CFArrayGetCount(runs);
    for (int j = 0; j < runCount; j++) {
        CTRunRef run = CFArrayGetValueAtIndex(runs, j);
        NSDictionary* attributes = (__bridge NSDictionary*)CTRunGetAttributes(run);
        NSString *imageTag = [attributes objectForKey:CHAT_IMAGE_TAG_NAME];
        if (imageTag) {
            CFRange range = CTRunGetStringRange(run);
//            NSLog(@"range: location = %li, length = %li", range.location, range.length);
//            NSLog(@"index:%ld",index);
            
            //判断点击的字符是否在需要处理点击事件的字符串范围内
            if (index >= range.location && index <= range.location + range.length) {
                ChatImage* chatImage = [[RunningCache sharedCache] chatImageForTag:imageTag];
                if (chatImage) {
                    if (chatImage.imageType == CHAT_IMAGE_TYPE_COMMON) { //普通图片
//                        UIAlertView* alert = [[UIAlertView alloc]initWithTitle:@"click event" message:@"1111" delegate:self cancelButtonTitle:@"cancel" otherButtonTitles:@"ok", nil];
//                        [alert show];
                        if ([self.delegate respondsToSelector:@selector(chatImageClick:)]) {
                            [self.delegate chatImageClick:chatImage];
                        }
                    }
                }
                break;
            }
        }
    }
}
@end

